#pragma once
#include "log.hpp"
#include <cerrno>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include<iostream>
#include<unordered_map>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<cstring>
#include<unistd.h>

class UdpServer
{
public:
    UdpServer(uint16_t port,std::string ip = "")
    :_port(port),_ip(ip)
    {

    }
    bool initServer()
    {
        _sock = socket(AF_INET, SOCK_DGRAM, 0);
        if(_sock < 0)
        {
            LogMessage(FATAL, "%d:%s", errno,strerror(errno));
            exit(-1);
        }
        struct sockaddr_in server;
        bzero(&server,sizeof(server));
        socklen_t len = sizeof(server);
        server.sin_family=AF_INET;
        server.sin_port=htons(_port);
        server.sin_addr.s_addr=inet_addr(_ip.c_str());
        if(bind(_sock, (struct sockaddr*)&server, len) < 0)
        {
            LogMessage(FATAL, "%d:%s", errno,strerror(errno));
            exit(-1);
        }
        return true;
    }
    void Start()
    {
        char buffer[1024];
        while(true)
        {
            char key[1024];
            uint16_t client_port;
            std::string client_ip;
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            ssize_t s = recvfrom(_sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&client, &len);
            if(s > 0)
            {
                buffer[s] = 0;
                client_port = ntohs(client.sin_port);
                client_ip = inet_ntoa(client.sin_addr);
                ////char key[1024];
                snprintf(key , sizeof(key), "%s:%u", client_ip.c_str(),client_port);
                auto it = _users.find(key);
                if(it == _users.end()){
                    _users.insert({key,client});
                }
            }
            for(auto& iter : _users)
            {
                    std::string sendMessage;
                    sendMessage = key;
                    sendMessage += "#";
                    sendMessage += buffer;
                    sendto(_sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&(iter.second), sizeof(iter.second));
            }
        }
    }
    ~UdpServer(){
        if(_sock >= 0){
            close(_sock);
        }
    }
private:
    int _sock;
    uint16_t _port;
    std::string _ip;
    std::unordered_map<std::string, struct sockaddr_in> _users;
};
// class UdpServer
// {
// public:
//     UdpServer(uint16_t port,std::string ip= "")
//     :_port(port),_ip(ip)
//     {

//     }
//     bool initServer()
//     {
//         _sock = socket(AF_INET, SOCK_DGRAM, 0);
//         if(_sock < 0)
//         {
//             LogMessage(FATAL, "%d:%s", errno,strerror(errno));
//             exit(-1);
//         }
//         struct sockaddr_in server;
//         socklen_t len = sizeof(server);
//         server.sin_family=AF_INET;
//         server.sin_port=htons(_port);
//         server.sin_addr.s_addr=inet_addr(_ip.c_str());
//         if(bind(_sock, (struct sockaddr*)&server, len) < 0)
//         {
//             LogMessage(FATAL, "%d:%s", errno,strerror(errno));
//             exit(-1);
//         }
//         return true;
//     }
//     void Start()
//     {
//         char buffer[1024];
//         while(true)
//         {
//             uint16_t client_port;
//             std::string client_ip;
//             struct sockaddr_in client;
//             socklen_t len = sizeof(client);
//             ssize_t s = recvfrom(_sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&client, &len);
//             char key[1024];
//             if(s > 0)
//             {
//                 buffer[s] = 0;
//                 client_port=ntohs(client.sin_port);
//                 client_ip=inet_ntoa(client.sin_addr);
//                 //key值这里需要使用所以必须进行填充
//                 snprintf(key, sizeof(key), "{%s:%u}", client_ip.c_str(),client_port);
//                 auto it = _users.find(key);
//                 if(it == _users.end()){
//                     _users.insert({key,client});
//                 }
//             }
//             for(auto& iter : _users){
//                 std::string sendMessage;
//                 sendMessage = key;
//                 sendMessage+="#";
//                 sendMessage += buffer;
//                 sendto(_sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&client, sizeof(client));
//             }
//         }
//     }
//     ~UdpServer(){
//         if(_sock >= 0){
//             close(_sock);
//         }
//     }
// private:
//     int _sock;
//     uint16_t _port;
//     std::string _ip;
//     std::unordered_map<std::string , struct sockaddr_in> _users;
// };
// class UdpServer
// {
// public:
//     UdpServer(uint16_t port,std::string ip = "")
//     :_port(port),_ip(ip)
//     {

//     }
//     bool initServer()
//     {
//         _sock = socket(AF_INET, SOCK_DGRAM, 0);
//         if(_sock < 0)
//         {
//             LogMessage(FATAL, "%d : %s", errno, strerror(errno));
//             exit(-1);
//         }
//         struct sockaddr_in server;
//         bzero(&server,sizeof(server));
//         server.sin_family=AF_INET;
//         server.sin_port=htons(_port);
//         server.sin_addr.s_addr=_ip.empty()?INADDR_ANY:inet_addr(_ip.c_str());
//         if(bind(_sock, (struct sockaddr*)&server, sizeof(server)) < 0)
//         {
//             LogMessage(FATAL, "%d:%s", errno,strerror(errno));
//             exit(-1);
//         }
//         LogMessage(NORMAL, "init udp server done ... %s", strerror(errno));
//         return true;
//     }
//     void Start()
//     {
//         char buffer[1024];
//         while(true)
//         {
//             struct sockaddr_in client;
//             bzero(&client,sizeof(client));
//             socklen_t len=sizeof(client);
//             char result[1024];
//             char key[1024];
//             //客户端的地址空间结构会存放在这里
//             ssize_t s = recvfrom(_sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&client, &len);
//             if(s > 0)
//             {
//                 buffer[s] = 0;
//                 uint16_t client_port = ntohs(client.sin_port);
//                 std::string client_ip = inet_ntoa(client.sin_addr);
//                 snprintf(key, sizeof(key), "%s-%u", client_ip.c_str(),client_port);
//                 LogMessage(NORMAL, "key : %s", key);
//                 auto it = _users.find(key);
//                 if(it == _users.end())
//                 {
//                     LogMessage(NORMAL, "add new user : %s", key);
//                     _users.insert({key,client});
//                 }
//             }
//             for(auto& iter : _users){
//                 std::string sendMessage = key;
//                 sendMessage += "#";
//                 sendMessage += buffer;
//                 LogMessage(NORMAL, "push message to %s", iter.first.c_str());
//                 sendto(_sock, sendMessage.c_str(), sendMessage.size(), 0, (struct sockaddr*)&(iter.second), sizeof(iter.second));
//             }
//         }
//     }
//     ~UdpServer(){
//         if(_sock >= 0){
//             close(_sock);
//         }
//     }
// private:
//     uint16_t _port;
//     std::string _ip;
//     int _sock;
//     std::unordered_map<std::string , struct sockaddr_in> _users;
// };
